home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PRINTER / JPSRC11.ARJ / JETRST.C < prev    next >
C/C++ Source or Header  |  1991-08-04  |  29KB  |  1,010 lines

  1. /*
  2.  *      JET PAK - HP DeskJet and LaserJet series printer utilities
  3.  *
  4.  *      JETRST program - restore soft font file from symbolic dump
  5.  *
  6.  *      Version 1.1 (Public Domain)
  7.  */
  8.  
  9. /* system include files */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13.  
  14. /* application include files */
  15. #include "patchlev.h"
  16. #include "jetfont.h"
  17. #include "jetutil.h"
  18. #include "jetbmp.h"
  19.  
  20. /*
  21.  * MODULE GLOBAL DATA
  22.  */
  23.  
  24. /* scratch area for decompressed DJ bitmap */
  25. static char scratch[BITMAP_SIZE_MAX];
  26.  
  27. /* token read from file */
  28. static char token[1000];
  29.  
  30. /* input line being read (used for error reporting only) */
  31. static int line;
  32.  
  33. /* font command being processed */
  34. static FONT_COMMAND fc;
  35.  
  36. /* get_token() can return these values (also EOF) */
  37. #define TOKEN_KEYWORD 1
  38. #define TOKEN_DATA    2
  39.  
  40. /* unget_token() stores the previous result here */
  41. static int unget_value;
  42.  
  43. /*
  44.  * LOCAL FUNCTIONS
  45.  */
  46.  
  47. static void usage_wrong()
  48. {
  49.     /*
  50.      * Print usage message and exit.
  51.      */
  52.     fprintf(stderr, USAGE_HEADER);
  53.     fprintf(stderr, "Usage: JETRST [-h] dumpfile [dumpfile...]\n\n");
  54.     fprintf(stderr, "Restore soft font files from symbolic listings\n\n");
  55.     fprintf(stderr, "  -h            print this usage information\n");
  56.     fprintf(stderr, "  dumpfile      dump file name\n");
  57.     exit(1);
  58. }
  59.  
  60. #define STATE_WAITING   0
  61. #define STATE_INTOKEN   1
  62. #define STATE_INSTRING  2
  63. #define STATE_EXIT      3
  64.  
  65. static int get_token(infp)
  66. FILE *infp;
  67. {
  68.     /*
  69.      * Read the next token from the dump file.
  70.      *
  71.      * Tokens are separated by white space (space, tab, new line, and
  72.      * form feed); they may also be terminated by special characters
  73.      * such as quote ("), comment indicator or keyword indicator.
  74.      *
  75.      * Data may be enclosed in quotes in which case white space may
  76.      * legimiately be included as part of the data; within quotes,
  77.      * \ is used to escape '"' and '\'.
  78.      *
  79.      * This routine returns EOF at end of file, TOKEN_KEYWORD if it
  80.      * finds a token beginning with the keyword indicator, otherwise
  81.      * TOKEN_DATA is returned.
  82.      */
  83.     int c, result = EOF, i = 0, state = STATE_WAITING;
  84.     int newline_warning = FALSE, token_warning = FALSE;
  85.  
  86.     /* check for pushed back token */
  87.     if (unget_value != 0)
  88.     {
  89.         result = unget_value;
  90.         unget_value = 0;
  91.     }
  92.     else
  93.     {
  94.         do
  95.         {
  96.             switch(c = getc(infp))
  97.             {
  98.             case EOF:
  99.                 ungetc(c, infp);
  100.                 token[i] = '\0';
  101.                 state = STATE_EXIT;
  102.                 break;
  103.  
  104.             case '\n':
  105.             case '\f':
  106.             case  ' ':
  107.             case '\t':
  108.                 if (state == STATE_INTOKEN)
  109.                 {
  110.                     /* white space terminates token */
  111.                     ungetc(c, infp);
  112.                     token[i] = '\0';
  113.                     state = STATE_EXIT;
  114.  
  115.                     /* don't increment line count here, because the
  116.                        /n is pushed back and re-read! */
  117.                 }
  118.                 else if (state == STATE_INSTRING)
  119.                 {
  120.                     /* give warning first time newline is found in a
  121.                        string as this is probably an error */
  122.                     if (c == '\n')
  123.                     {
  124.                         if (!newline_warning)
  125.                         {
  126.                             newline_warning = TRUE;
  127.                             fprintf(stderr, WARNING_STRING_NL,
  128.                                     os_dir, os_file, line);
  129.                         }
  130.  
  131.                         line++;     /* line completed */
  132.                     }
  133.  
  134.                     /* space and tab allowed in string */
  135.                     token[i++] = (char)c;
  136.                 }
  137.                 else    /* state == STATE_WAITING */
  138.                 {
  139.                     if (c == '\n')
  140.                         line++;     /* line completed */
  141.                 }
  142.                 break;
  143.  
  144.             case COMMENT_CHARACTER:
  145.                 if (state == STATE_WAITING)
  146.                 {
  147.                     /* consume comment */
  148.                     while ((c = getc(infp)) != EOF && c != '\n')
  149.                         ;
  150.                     ungetc(c, infp);
  151.  
  152.                     if (c == EOF)
  153.                     {
  154.                         token[i] = '\0';
  155.                         state = STATE_EXIT;
  156.                     }
  157.                 }
  158.                 else if (state == STATE_INSTRING)
  159.                 {
  160.                     /* comment character is just part of the string */
  161.                     token[i++] = (char)c;
  162.                 }
  163.                 else    /* state == STATE_INTOKEN */
  164.                 {
  165.                     /* comment character terminates token */
  166.                     ungetc(c, infp);
  167.                     token[i] = '\0';
  168.                     state = STATE_EXIT;
  169.                 }
  170.                 break;
  171.  
  172.             case KEYWORD_CHARACTER:
  173.                 if (state == STATE_WAITING)
  174.                 {
  175.                    /* start of keyword token*/
  176.                    result = TOKEN_KEYWORD;
  177.                    state = STATE_INTOKEN;
  178.                 }
  179.                 /* keyword character is just part of the token */
  180.                 token[i++] = (char)c;
  181.                 break;
  182.  
  183.             case '"':
  184.                 if (state == STATE_WAITING)
  185.                 {
  186.                     /* start of string data */
  187.                     result = TOKEN_DATA;
  188.                     state = STATE_INSTRING;
  189.                 }
  190.                 else if (state == STATE_INSTRING)
  191.                 {
  192.                     /* end of string data */
  193.                     token[i] = '\0';
  194.                     state = STATE_EXIT;
  195.                 }
  196.                 else    /* state == STATE_INTOKEN */
  197.                 {
  198.                     /* quote character terminates a token */
  199.                     ungetc(c, infp);
  200.                     token[i] = '\0';
  201.                     state = STATE_EXIT;
  202.                 }
  203.                 break;
  204.  
  205.             case '\\':
  206.                 if (state == STATE_INSTRING)
  207.                 {
  208.                     /* escaped '\' or '"' */
  209.                     if ((c = getc(infp)) == EOF)
  210.                     {
  211.                         ungetc(c, infp);
  212.                         token[i] = '\0';
  213.                         state = STATE_EXIT;
  214.                         break;
  215.                     }
  216.                 }
  217.  
  218.                 /* !! INTENTIONAL DROP-THROUGH !! */
  219.  
  220.             default:
  221.                 if (state == STATE_WAITING)
  222.                 {
  223.                     /* start of regular data */
  224.                     result = TOKEN_DATA;
  225.                     state = STATE_INTOKEN;
  226.                 }
  227.                 /* regular character as part of token or string */
  228.                 token[i++] = (char)c;
  229.                 break;
  230.             }
  231.  
  232.             /* check for token overflow */
  233.             if (i == sizeof(token))
  234.             {
  235.                 i--;
  236.  
  237.                 if (!token_warning)
  238.                 {
  239.                     token_warning = TRUE;
  240.                     fprintf(stderr, WARNING_TOKEN_OVERFLOW,
  241.                             os_dir, os_file, line-1);
  242.  
  243.                 }
  244.             }
  245.  
  246.         } while (state != STATE_EXIT);
  247.     }
  248.  
  249.     return(result);
  250. }
  251. static void unget_token(result)
  252. int result;
  253. {
  254.     /*
  255.      * Push back token so it will be returned by the next
  256.      * get_token(). Only one level of unget_token() is supported.
  257.      */
  258.     unget_value = result;
  259. }
  260.  
  261. static int get_unsigned_byte(infp, p)
  262. FILE *infp;
  263. UNSIGNEDBYTE *p;
  264. {
  265.     /*
  266.      * Read a token to be interpreted as UNSIGNEDBYTE; store the
  267.      * result in *p, if data is read successfully.
  268.      */
  269.     int result;
  270.     UNSIGNEDINT value;
  271.  
  272.     if ((result = get_token(infp)) == TOKEN_DATA)
  273.     {
  274.         sscanf(token, "%hu", &value);
  275.         *p = (UNSIGNEDBYTE)value;
  276.     }
  277.  
  278.     return(result);
  279. }
  280. static int get_signed_byte(infp, p)
  281. FILE *infp;
  282. SIGNEDBYTE *p;
  283. {
  284.     /*
  285.      * Read a token to be interpreted as SIGNEDBYTE; store the
  286.      * result in *p, if data is read successfully.
  287.      */
  288.     int result;
  289.     SIGNEDINT value;
  290.  
  291.     if ((result = get_token(infp)) == TOKEN_DATA)
  292.     {
  293.         sscanf(token, "%hd", &value);
  294.         *p = (SIGNEDBYTE)value;
  295.     }
  296.  
  297.     return(result);
  298. }
  299. static int get_unsigned_int(infp, p)
  300. FILE *infp;
  301. UNSIGNEDINT *p;
  302. {
  303.     /*
  304.      * Read a token to be interpreted as UNSIGNEDINT; store the
  305.      * result in *p, if data is read successfully.
  306.      */
  307.     int result;
  308.  
  309.     if ((result = get_token(infp)) == TOKEN_DATA)
  310.         sscanf(token, "%hu", p);
  311.  
  312.     return(result);
  313. }
  314. static int get_signed_int(infp, p)
  315. FILE *infp;
  316. SIGNEDINT *p;
  317. {
  318.     /*
  319.      * Read a token to be interpreted as SIGNEDINT; store the
  320.      * result in *p, if data is read successfully.
  321.      */
  322.     int result;
  323.  
  324.     if ((result = get_token(infp)) == TOKEN_DATA)
  325.         sscanf(token, "%hd", p);
  326.  
  327.     return(result);
  328. }
  329.  
  330. static int bitmap_data_restore(infp, bp, cw, ch, dsize)
  331. FILE *infp;
  332. UNSIGNEDBYTE *bp;
  333. UNSIGNEDINT cw, ch;
  334. UNSIGNEDINT dsize;
  335. {
  336.     /*
  337.      * Restore the data in the bitmap record, returning the number of
  338.      * bytes read if successful.
  339.      */
  340.     int result;
  341.     register UNSIGNEDBYTE *bp2 = bp;
  342.     register UNSIGNEDINT pmask;
  343.     UNSIGNEDINT x, len;
  344.  
  345.     /* check sufficient space is available */
  346.     if ((((cw + 7)/8)*ch) > dsize)
  347.         return(ERROR);
  348.  
  349.     while (ch-- > 0)
  350.     {
  351.         /* read a row - tolerate (ie clear) missing rows at bottom of bitmap */
  352.         if ((result = get_token(infp)) == TOKEN_DATA)
  353.         {
  354.             len = strlen(token);
  355.         }
  356.         else
  357.         {
  358.             unget_token(result);
  359.             len = 0;
  360.         }
  361.  
  362.         *bp2 = 0;
  363.         for (x = 0, pmask = 0x80; x < cw; x++, pmask >>= 1)
  364.         {
  365.             if (pmask == 0)
  366.             {
  367.                 pmask = 0x80;
  368.                 bp2++;
  369.                 *bp2 = 0;
  370.             }
  371.  
  372.             /* tolerate (ie clear) missing bits at end of row */
  373.             if ((x < len) && (token[x] == '@'))
  374.                 *bp2 |= pmask;
  375.         }
  376.         bp2++;
  377.     }
  378.  
  379.     return((int)(bp2 - bp));
  380. }
  381.  
  382. static int bitmap_restore(infp, outfp)
  383. FILE *infp;
  384. FILE *outfp;
  385. {
  386.     /*
  387.      * Restore a bitmap record
  388.      */
  389.     int result;
  390.  
  391.     /* read the bitmap data */
  392.     switch(fc.data.character.format)
  393.     {
  394.     default:
  395.     case LJCHARFORMAT:
  396.         if ((result = bitmap_data_restore(infp,
  397.                     fc.data.character.data.ljchar.bitmap,
  398.                     fc.data.character.data.ljchar.character_width,
  399.                     fc.data.character.data.ljchar.character_height,
  400.                     sizeof(fc.data.character.data.ljchar.bitmap))) == ERROR)
  401.         {
  402.             fprintf(stderr, ERROR_BITMAP_TOO_BIG, os_dir, os_file);
  403.             return(ERROR);
  404.         }
  405.         fc.number += result;
  406.  
  407.         break;
  408.     case DJCHARFORMAT:
  409.     case DJPCHARFORMAT:
  410.     case DJ500CHARFORMAT:
  411.         if ((result = bitmap_data_restore(infp,
  412.                     scratch,
  413.                     fc.data.character.data.djchar.character_width,
  414.                     PASS_HEIGHT,
  415.                     sizeof(scratch))) == ERROR)
  416.         {
  417.             fprintf(stderr, ERROR_BITMAP_TOO_BIG, os_dir, os_file);
  418.             return(ERROR);
  419.         }
  420.  
  421.         if ((result = bitmap_compress(scratch,
  422.                     fc.data.character.data.djchar.character_width,
  423.                     PASS_HEIGHT,
  424.                     fc.data.character.data.djchar.bitmap,
  425.                     sizeof(fc.data.character.data.djchar.bitmap))) == ERROR)
  426.         {
  427.             fprintf(stderr, ERROR_BITMAP_TOO_BIG, os_dir, os_file);
  428.             return(ERROR);
  429.         }
  430.         fc.number += result;
  431.  
  432.         break;
  433.     }
  434.  
  435.     /* write out the character descriptor and associated bitmap */
  436.     if (font_command_write(outfp, &fc) == ERROR)
  437.     {
  438.         fprintf(stderr, ERROR_FILE_WRITE_FAILED, os_dir, os_file);
  439.         return(ERROR);
  440.     }
  441.  
  442.     return(OK);
  443. }
  444.  
  445. static int header_data_restore(infp)
  446. FILE *infp;
  447. {
  448.     /*
  449.      * Restore the data in the header record
  450.      */
  451.     FONT_DESCRIPTOR *fdp = &fc.data.font;
  452.     int result;
  453.  
  454.     fc.command_type = FDC;
  455.  
  456.     if ((result = get_unsigned_int(infp, &fdp->size)) != TOKEN_DATA)
  457.         return(result);
  458.  
  459.     if ((result = get_unsigned_byte(infp, &fdp->header_format)) != TOKEN_DATA)
  460.         return(result);
  461.  
  462.     if ((result = get_unsigned_byte(infp, &fdp->type)) != TOKEN_DATA)
  463.         return(result);
  464.  
  465.     if ((result = get_unsigned_int(infp, &fdp->reserved1)) != TOKEN_DATA)
  466.         return(result);
  467.  
  468.     if ((result = get_unsigned_int(infp, &fdp->baseline_distance)) != TOKEN_DATA)
  469.         return(result);
  470.  
  471.     if ((result = get_unsigned_int(infp, &fdp->cell_width)) != TOKEN_DATA)
  472.         return(result);
  473.  
  474.     if ((result = get_unsigned_int(infp, &fdp->cell_height)) != TOKEN_DATA)
  475.         return(result);
  476.  
  477.     if ((result = get_unsigned_byte(infp, &fdp->orientation)) != TOKEN_DATA)
  478.         return(result);
  479.  
  480.     if ((result = get_unsigned_byte(infp, &fdp->spacing)) != TOKEN_DATA)
  481.         return(result);
  482.  
  483.     if ((result = get_unsigned_int(infp, &fdp->symbol_set)) != TOKEN_DATA)
  484.         return(result);
  485.  
  486.     if ((result = get_unsigned_int(infp, &fdp->pitch)) != TOKEN_DATA)
  487.         return(result);
  488.  
  489.     if ((result = get_unsigned_int(infp, &fdp->height)) != TOKEN_DATA)
  490.         return(result);
  491.  
  492.     if ((result = get_unsigned_int(infp, &fdp->x_height)) != TOKEN_DATA)
  493.         return(result);
  494.  
  495.     if ((result = get_signed_byte(infp, &fdp->width_type)) != TOKEN_DATA)
  496.         return(result);
  497.  
  498.     if ((result = get_unsigned_int(infp, &fdp->style)) != TOKEN_DATA)
  499.         return(result);
  500.  
  501.     if ((result = get_signed_byte(infp, &fdp->stroke_weight)) != TOKEN_DATA)
  502.         return(result);
  503.  
  504.     if ((result = get_unsigned_int(infp, &fdp->typeface)) != TOKEN_DATA)
  505.         return(result);
  506.  
  507.     if ((result = get_unsigned_byte(infp, &fdp->slant)) != TOKEN_DATA)
  508.         return(result);
  509.  
  510.     if ((result = get_unsigned_byte(infp, &fdp->serif_style)) != TOKEN_DATA)
  511.         return(result);
  512.  
  513.     if ((result = get_unsigned_byte(infp, &fdp->quality)) != TOKEN_DATA)
  514.         return(result);
  515.  
  516.     if ((result = get_signed_byte(infp, &fdp->placement)) != TOKEN_DATA)
  517.         return(result);
  518.  
  519.     if ((result = get_signed_byte(infp, &fdp->underline_distance)) != TOKEN_DATA)
  520.         return(result);
  521.  
  522.     if ((result = get_unsigned_byte(infp, &fdp->underline_height)) != TOKEN_DATA)
  523.         return(result);
  524.  
  525.     if ((result = get_unsigned_int(infp, &fdp->text_height)) != TOKEN_DATA)
  526.         return(result);
  527.  
  528.     if ((result = get_unsigned_int(infp, &fdp->text_width)) != TOKEN_DATA)
  529.         return(result);
  530.  
  531.     if ((result = get_unsigned_int(infp, &fdp->first_code)) != TOKEN_DATA)
  532.         return(result);
  533.  
  534.     if ((result = get_unsigned_int(infp, &fdp->last_code)) != TOKEN_DATA)
  535.         return(result);
  536.  
  537.     if ((result = get_unsigned_byte(infp, &fdp->pitch_extended)) != TOKEN_DATA)
  538.         return(result);
  539.  
  540.     if ((result = get_unsigned_byte(infp, &fdp->height_extended)) != TOKEN_DATA)
  541.         return(result);
  542.  
  543.     if ((result = get_unsigned_int(infp, &fdp->reserved2)) != TOKEN_DATA)
  544.         return(result);
  545.  
  546.     if ((result = get_unsigned_int(infp, &fdp->font_number_top)) != TOKEN_DATA)
  547.         return(result);
  548.  
  549.     if ((result = get_unsigned_int(infp, &fdp->font_number_bot)) != TOKEN_DATA)
  550.         return(result);
  551.  
  552.     if ((result = get_unsigned_int(infp, &fdp->h_pixel_resolution)) != TOKEN_DATA)
  553.         return(result);
  554.  
  555.     if ((result = get_unsigned_int(infp, &fdp->v_pixel_resolution)) != TOKEN_DATA)
  556.         return(result);
  557.  
  558.     if ((result = get_signed_byte(infp, &fdp->tdu_distance)) != TOKEN_DATA)
  559.         return(result);
  560.  
  561.     if ((result = get_unsigned_byte(infp, &fdp->tdu_height)) != TOKEN_DATA)
  562.         return(result);
  563.  
  564.     if ((result = get_signed_byte(infp, &fdp->bdu_distance)) != TOKEN_DATA)
  565.         return(result);
  566.  
  567.     if ((result = get_unsigned_byte(infp, &fdp->bdu_height)) != TOKEN_DATA)
  568.         return(result);
  569.  
  570.     if ((result = get_unsigned_int(infp, &fdp->specific_size)) != TOKEN_DATA)
  571.         return(result);
  572.  
  573.     if ((result = get_unsigned_int(infp, &fdp->data_size)) != TOKEN_DATA)
  574.         return(result);
  575.  
  576.     if ((result = get_unsigned_byte(infp, &fdp->unidirection)) != TOKEN_DATA)
  577.         return(result);
  578.  
  579.     if ((result = get_unsigned_byte(infp, &fdp->compressed)) != TOKEN_DATA)
  580.         return(result);
  581.  
  582.     if ((result = get_unsigned_byte(infp, &fdp->hold_time_factor)) != TOKEN_DATA)
  583.         return(result);
  584.  
  585.     if ((result = get_unsigned_byte(infp, &fdp->no_half_pitch)) != TOKEN_DATA)
  586.         return(result);
  587.  
  588.     if ((result = get_unsigned_byte(infp, &fdp->no_double_pitch)) != TOKEN_DATA)
  589.         return(result);
  590.  
  591.     if ((result = get_unsigned_byte(infp, &fdp->no_half_height)) != TOKEN_DATA)
  592.         return(result);
  593.  
  594.     if ((result = get_unsigned_byte(infp, &fdp->no_bold)) != TOKEN_DATA)
  595.         return(result);
  596.  
  597.     if ((result = get_unsigned_byte(infp, &fdp->no_draft)) != TOKEN_DATA)
  598.         return(result);
  599.  
  600.     if ((result = get_unsigned_byte(infp, &fdp->bold_method)) != TOKEN_DATA)
  601.         return(result);
  602.  
  603.     if ((result = get_unsigned_byte(infp, &fdp->reserved3)) != TOKEN_DATA)
  604.         return(result);
  605.  
  606.     if ((result = get_unsigned_int(infp, &fdp->baseline_offset_2)) != TOKEN_DATA)
  607.         return(result);
  608.  
  609.     if ((result = get_unsigned_int(infp, &fdp->baseline_offset_3)) != TOKEN_DATA)
  610.         return(result);
  611.  
  612.     if ((result = get_unsigned_int(infp, &fdp->baseline_offset_4)) != TOKEN_DATA)
  613.         return(result);
  614.  
  615.     return(get_token(infp));
  616. }
  617.  
  618. static int header_restore(infp, outfp)
  619. FILE *infp;
  620. FILE *outfp;
  621. {
  622.     /*
  623.      * Restore the font descriptor records
  624.      */
  625.     int result;
  626.  
  627.     /* check for header keyword */
  628.     if (    ((result = get_token(infp)) != TOKEN_KEYWORD)
  629.          || (strcmp(token, KEYWORD_HEADER) != 0) )
  630.     {
  631.         fprintf(stderr, ERROR_KEYWORD_MISSING, os_dir, os_file, line);
  632.         unget_token(result);
  633.         return(ERROR);
  634.     }
  635.  
  636.     /* get header data and check for name keyword */
  637.     if (    ((result = header_data_restore(infp)) != TOKEN_KEYWORD)
  638.          || (strcmp(token, KEYWORD_NAME) != 0) )
  639.     {
  640.         fprintf(stderr, ERROR_KEYWORD_MISSING, os_dir, os_file, line);
  641.         unget_token(result);
  642.         return(ERROR);
  643.     }
  644.  
  645.     /* get name data */
  646.     if ((result = get_token(infp)) != TOKEN_DATA)
  647.     {
  648.        fprintf(stderr, ERROR_DATA_MISSING, os_dir, os_file, line);
  649.        unget_token(result);
  650.        return(ERROR);
  651.     }
  652.     strncpy(fc.data.font.name, token, sizeof(fc.data.font.name));
  653.  
  654.     if (fc.data.font.header_format == DJ500FONTFORMAT)
  655.     {
  656.         /* also copy the name extension for DJ500 only */
  657.         strncpy(fc.data.font.name_extension, token+sizeof(fc.data.font.name),
  658.                             sizeof(fc.data.font.name_extension));
  659.     }
  660.  
  661.     /* fix up the descriptor size and number */
  662.     switch(fc.data.font.header_format)
  663.     {
  664.     default:
  665.         fprintf(stderr, WARNING_BAD_FONT_FORMAT,
  666.                     os_dir, os_file, fc.data.font.header_format);
  667.  
  668.         /* !! INTENTIONAL DROP-THROUGH !! */
  669.  
  670.     case LJFONTFORMAT:
  671.         fc.data.font.size = LJFDSIZE;
  672.         fc.number = LJFDSIZE+LJSSIZE;
  673.  
  674.         break;
  675.     case DJFONTFORMAT:
  676.     case DJPFONTFORMAT:
  677.         fc.data.font.size = DJFDSIZE;
  678.         fc.number = DJFDSIZE+DJSSIZE;
  679.  
  680.         break;
  681.     case DJ500FONTFORMAT:
  682.         fc.data.font.size = DJ500FDSIZE;
  683.         fc.number = DJ500FDSIZE+DJ500SSIZE;
  684.  
  685.         break;
  686.     }
  687.  
  688.     /* check for comment keyword */
  689.     if (    ((result = get_token(infp)) != TOKEN_KEYWORD)
  690.          || (strcmp(token, KEYWORD_COMMENT) != 0) )
  691.     {
  692.         fprintf(stderr, ERROR_KEYWORD_MISSING, os_dir, os_file, line);
  693.         unget_token(result);
  694.         return(ERROR);
  695.     }
  696.  
  697.     /* get comment data */
  698.     if ((result = get_token(infp)) != TOKEN_DATA)
  699.     {
  700.        fprintf(stderr, ERROR_DATA_MISSING, os_dir, os_file, line);
  701.        unget_token(result);
  702.        return(ERROR);
  703.     }
  704.     strncpy(fc.data.font.comment, token, COMMENT_SIZE_MAX-1);
  705.     fc.data.font.comment[COMMENT_SIZE_MAX-1] = '\0';   /* failsafe */
  706.     fc.number += strlen(fc.data.font.comment);
  707.  
  708.     /* write out the header */
  709.     if (font_command_write(outfp, &fc) == ERROR)
  710.     {
  711.         fprintf(stderr, ERROR_FILE_WRITE_FAILED, os_dir, os_file);
  712.         return(ERROR);
  713.     }
  714.  
  715.     return(OK);
  716. }
  717.  
  718. static int character_data_restore(infp)
  719. FILE *infp;
  720. {
  721.     /*
  722.      * Restore the data in the character descriptor
  723.      */
  724.     struct ljchar_struct *ljcp;
  725.     struct djchar_struct *djcp;
  726.     int result;
  727.  
  728.     fc.number = 0;
  729.     fc.command_type = CDC;
  730.  
  731.     if ((result = get_unsigned_byte(infp, &fc.data.character.format)) != TOKEN_DATA)
  732.         return(result);
  733.     fc.number += 1;
  734.  
  735.     if ((result = get_unsigned_byte(infp, &fc.data.character.continuation)) != TOKEN_DATA)
  736.         return(result);
  737.     fc.number += 1;
  738.  
  739.     switch(fc.data.character.format)
  740.     {
  741.     default:
  742.         fprintf(stderr, WARNING_BAD_CHAR_FORMAT,
  743.                     os_dir, os_file, fc.data.character.format);
  744.  
  745.         /* !! INTENTIONAL DROP-THROUGH !! */
  746.  
  747.     case LJCHARFORMAT:
  748.         ljcp = &fc.data.character.data.ljchar;
  749.  
  750.         if ((result = get_unsigned_byte(infp, &ljcp->descriptor_size)) != TOKEN_DATA)
  751.             return(result);
  752.         fc.number += 1;
  753.  
  754.         if ((result = get_unsigned_byte(infp, &ljcp->class)) != TOKEN_DATA)
  755.             return(result);
  756.         fc.number += 1;
  757.  
  758.         if ((result = get_unsigned_byte(infp, &ljcp->orientation)) != TOKEN_DATA)
  759.             return(result);
  760.         fc.number += 1;
  761.  
  762.         if ((result = get_unsigned_byte(infp, &ljcp->reserved)) != TOKEN_DATA)
  763.             return(result);
  764.         fc.number += 1;
  765.  
  766.         if ((result = get_signed_int(infp, &ljcp->left_offset)) != TOKEN_DATA)
  767.             return(result);
  768.         fc.number += 2;
  769.  
  770.         if ((result = get_signed_int(infp, &ljcp->top_offset)) != TOKEN_DATA)
  771.             return(result);
  772.         fc.number += 2;
  773.  
  774.         if ((result = get_unsigned_int(infp, &ljcp->character_width)) != TOKEN_DATA)
  775.             return(result);
  776.         fc.number += 2;
  777.  
  778.         if ((result = get_unsigned_int(infp, &ljcp->character_height)) != TOKEN_DATA)
  779.             return(result);
  780.         fc.number += 2;
  781.  
  782.         if ((result = get_signed_int(infp, &ljcp->delta_x)) != TOKEN_DATA)
  783.             return(result);
  784.         fc.number += 2;
  785.  
  786.         break;
  787.     case DJCHARFORMAT:
  788.     case DJPCHARFORMAT:
  789.     case DJ500CHARFORMAT:
  790.         djcp = &fc.data.character.data.djchar;
  791.  
  792.         if ((result = get_unsigned_byte(infp, &djcp->descriptor_size)) != TOKEN_DATA)
  793.             return(result);
  794.         fc.number += 1;
  795.  
  796.         if ((result = get_unsigned_byte(infp, &djcp->char_type)) != TOKEN_DATA)
  797.             return(result);
  798.         fc.number += 1;
  799.  
  800.         if ((result = get_unsigned_byte(infp, &djcp->character_width)) != TOKEN_DATA)
  801.             return(result);
  802.         fc.number += 1;
  803.  
  804.         if ((result = get_unsigned_byte(infp, &djcp->comp_width)) != TOKEN_DATA)
  805.             return(result);
  806.         fc.number += 1;
  807.  
  808.         if ((result = get_signed_byte(infp, &djcp->left_offset)) != TOKEN_DATA)
  809.             return(result);
  810.         fc.number += 1;
  811.  
  812.         if ((result = get_signed_byte(infp, &djcp->right_offset)) != TOKEN_DATA)
  813.             return(result);
  814.         fc.number += 1;
  815.  
  816.         break;
  817.     }
  818.  
  819.     return(get_token(infp));
  820. }
  821.  
  822. static int character_restore(infp, outfp)
  823. FILE *infp;
  824. FILE *outfp;
  825. {
  826.     /*
  827.      * Restore a character descriptor record
  828.      */
  829.     int result;
  830.  
  831.     /* get and output the character code first */
  832.     if ((result = get_token(infp)) != TOKEN_DATA)
  833.     {
  834.         fprintf(stderr, ERROR_DATA_MISSING, os_dir, os_file, line);
  835.         unget_token(result);
  836.         return(ERROR);
  837.     }
  838.  
  839.     fc.command_type = CCC;
  840.     sscanf(token, "%d", &fc.number);
  841.  
  842.     /* write out the character code escape sequence */
  843.     if (font_command_write(outfp, &fc) == ERROR)
  844.     {
  845.         fprintf(stderr, ERROR_FILE_WRITE_FAILED, os_dir, os_file);
  846.         return(ERROR);
  847.     }
  848.  
  849.     /* get character data and check for bitmap keyword */
  850.     if (    ((result = character_data_restore(infp)) != TOKEN_KEYWORD)
  851.          || (strcmp(token, KEYWORD_BITMAP) != 0) )
  852.     {
  853.         fprintf(stderr, ERROR_KEYWORD_MISSING, os_dir, os_file, line);
  854.         unget_token(result);
  855.         return(ERROR);
  856.     }
  857.  
  858.     unget_token(result);
  859.  
  860.     return(OK);
  861. }
  862.  
  863. static int file_restore(infp, outfp)
  864. FILE *infp;
  865. FILE *outfp;
  866. {
  867.     int result;
  868.  
  869.     /* read the header information first */
  870.     if (header_restore(infp, outfp) == ERROR)
  871.         return(ERROR);
  872.  
  873.     while (    ((result = get_token(infp)) == TOKEN_KEYWORD)
  874.             && (strcmp(token, KEYWORD_CHAR) == 0) )
  875.     {
  876.         /* restore the character descriptor header */
  877.         if (character_restore(infp, outfp) == ERROR)
  878.             return(ERROR);
  879.  
  880.         /* must get bitmap data next */
  881.         if (    ((result = get_token(infp)) != TOKEN_KEYWORD)
  882.              || (strcmp(token, KEYWORD_BITMAP) != 0) )
  883.         {
  884.             fprintf(stderr, ERROR_KEYWORD_MISSING, os_dir, os_file, line);
  885.             unget_token(result);
  886.             return(ERROR);
  887.         }
  888.  
  889.         /* restore character descriptor bitmap data */
  890.         if (bitmap_restore(infp, outfp) == ERROR)
  891.             return(ERROR);
  892.     }
  893.  
  894.     /* check loop was exited either at EOF or on reading start of next
  895.        dumped file */
  896.     if (    (result == TOKEN_KEYWORD && strcmp(token, KEYWORD_FILE) != 0)
  897.          || (result == TOKEN_DATA) )
  898.     {
  899.         fprintf(stderr, ERROR_KEYWORD_MISSING, os_dir, os_file, line);
  900.         unget_token(result);
  901.         return(ERROR);
  902.     }
  903.  
  904.     unget_token(result);  /* because next token or EOF was read */
  905.  
  906.     return(OK);
  907. }
  908.  
  909. static void jetrst()
  910. {
  911.     char inpath[OS_PATH_LEN], outpath[OS_PATH_LEN];
  912.     FILE *infp, *outfp;
  913.     int result, file_found = FALSE;
  914.  
  915.     /* build the input and output file paths */
  916.     strcpy(inpath, os_dir);
  917.     strcat(inpath, os_file);
  918.  
  919.     if (!(infp = fopen(inpath, "r")))
  920.     {
  921.         fprintf(stderr, ERROR_OPEN_READ_FAILED, os_dir, os_file);
  922.         return;
  923.     }
  924.  
  925.     /* initialise per input file data */
  926.     line = 1;
  927.     unget_value = 0;
  928.  
  929.     /* skip up to file keyword or EOF */
  930.     while ((result = get_token(infp)) != EOF)
  931.     {
  932.         if (    (result == TOKEN_KEYWORD)
  933.              && (strcmp(token, KEYWORD_FILE) == 0) )
  934.         {
  935.             file_found = TRUE;
  936.  
  937.             /* read file name */
  938.             if ((result = get_token(infp)) != TOKEN_DATA)
  939.             {
  940.                 fprintf(stderr, ERROR_DATA_MISSING, os_dir, os_file, line);
  941.                 unget_token(result);
  942.                 continue;
  943.             }
  944.  
  945.             strncpy(outpath, token, OS_PATH_LEN-1);
  946.             outpath[OS_PATH_LEN-1] = '\0';  /* fail-safe NULL termination */
  947.  
  948.             /* rudimentary check for input overwriting output */
  949.             if (strcmp(inpath, outpath) == 0)
  950.             {
  951.                 fprintf(stderr, ERROR_OVERWRITE, os_dir, os_file);
  952.                 continue;
  953.             }
  954.  
  955.             if (!(outfp = fopen(outpath, "wb")))
  956.             {
  957.                 fprintf(stderr, ERROR_OPEN_WRITE_FAILED, os_dir, os_file, outpath);
  958.                 continue;
  959.             }
  960.  
  961.             if (file_restore(infp, outfp) == OK)
  962.                 fprintf(stderr, OK_JETRST, os_dir, os_file, outpath);
  963.  
  964.             fclose(outfp);
  965.         }
  966.     }
  967.  
  968.     if (!file_found)
  969.         fprintf(stderr, ERROR_FILE_READ_FAILED, os_dir, os_file);
  970.  
  971.     fclose(infp);
  972. }
  973.  
  974. /*
  975.  *  EXTERNAL FUNCTION
  976.  */
  977.  
  978. int main(argc, argv)
  979. int argc;
  980. char *argv[];
  981. {
  982.     char c;
  983.  
  984.     /* stop getopt() printing errors */
  985.     opterr = FALSE;
  986.     while ((c = getopt(argc, argv, "h")) != EOF)
  987.     {
  988.         switch (c)
  989.         {
  990.         case 'h':
  991.         case '?':
  992.             /* help required, or invalid option specified */
  993.             usage_wrong();
  994.         }
  995.     }
  996.  
  997.     /* must specify at least one file */
  998.     if (optind >= argc)
  999.         usage_wrong();
  1000.  
  1001.     /* process file arguments */
  1002.     if (os_findfiles((argc - optind), &argv[optind]) == ERROR)
  1003.         fprintf(stderr, ERROR_OUT_OF_HEAP);
  1004.  
  1005.     while (os_getfile() != EOF)
  1006.         jetrst();
  1007.  
  1008.     return(0);
  1009. }
  1010.